﻿using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;

namespace Utils.Wpf
{
	// Code taken from here: http://stackoverflow.com/questions/743906/how-to-hide-close-button-in-wpf-window
	public class WindowBehavior
	{
		#region HideCloseButton (attached property)

		public static readonly DependencyProperty HideCloseButtonProperty = DependencyProperty.RegisterAttached("HideCloseButton", typeof(bool), typeof(WindowBehavior), new FrameworkPropertyMetadata(false, WindowBehavior.HideCloseButtonChangedCallback));

		[AttachedPropertyBrowsableForType(typeof(Window))]
		public static bool GetHideCloseButton(Window obj)
		{
			return (bool)obj.GetValue(WindowBehavior.HideCloseButtonProperty);
		}

		[AttachedPropertyBrowsableForType(typeof(Window))]
		public static void SetHideCloseButton(Window obj, bool value)
		{
			obj.SetValue(WindowBehavior.HideCloseButtonProperty, value);
		}

		private static void HideCloseButtonChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			var window = d as Window;
			if (window == null) return;

			var hideCloseButton = (bool)e.NewValue;
			if (hideCloseButton && !WindowBehavior.GetIsHiddenCloseButton(window))
			{
				if (!window.IsLoaded)
				{
					window.Loaded += WindowBehavior.LoadedDelegate;
				}
				else
				{
					WindowBehavior.HideCloseButton(window);
				}
				WindowBehavior.SetIsHiddenCloseButton(window, true);
			}
			else if (!hideCloseButton && WindowBehavior.GetIsHiddenCloseButton(window))
			{
				if (!window.IsLoaded)
				{
					window.Loaded -= WindowBehavior.LoadedDelegate;
				}
				else
				{
					WindowBehavior.ShowCloseButton(window);
				}
				WindowBehavior.SetIsHiddenCloseButton(window, false);
			}
		}

		#region Win32 imports

		private const int GWL_STYLE = -16;
		private const int WS_SYSMENU = 0x80000;
		[DllImport("user32.dll", SetLastError = true)]
		private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
		[DllImport("user32.dll")]
		private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

		#endregion

		private static readonly RoutedEventHandler LoadedDelegate = (sender, args) =>
		{
			if (sender is Window == false) return;
			var w = (Window)sender;
			WindowBehavior.HideCloseButton(w);
			w.Loaded -= WindowBehavior.LoadedDelegate;
		};

		private static void HideCloseButton(Window w)
		{
			var hwnd = new WindowInteropHelper(w).Handle;
			WindowBehavior.SetWindowLong(hwnd, GWL_STYLE, WindowBehavior.GetWindowLong(hwnd, GWL_STYLE) & ~WS_SYSMENU);
		}

		private static void ShowCloseButton(Window w)
		{
			var hwnd = new WindowInteropHelper(w).Handle;
			WindowBehavior.SetWindowLong(hwnd, GWL_STYLE, WindowBehavior.GetWindowLong(hwnd, GWL_STYLE) | WS_SYSMENU);
		}

		#endregion

		#region IsHiddenCloseButton (readonly attached property)

		private static readonly DependencyPropertyKey IsHiddenCloseButtonKey = DependencyProperty.RegisterAttachedReadOnly("IsHiddenCloseButton",typeof(bool),typeof(WindowBehavior),new FrameworkPropertyMetadata(false));

		public static readonly DependencyProperty IsHiddenCloseButtonProperty = WindowBehavior.IsHiddenCloseButtonKey.DependencyProperty;

		[AttachedPropertyBrowsableForType(typeof(Window))]
		public static bool GetIsHiddenCloseButton(Window obj)
		{
			return (bool)obj.GetValue(WindowBehavior.IsHiddenCloseButtonProperty);
		}

		private static void SetIsHiddenCloseButton(Window obj, bool value)
		{
			obj.SetValue(WindowBehavior.IsHiddenCloseButtonKey, value);
		}

		#endregion

	}
}
